package com.qiwenshare.file.service;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qiwenshare.common.util.DateUtil;
import com.qiwenshare.common.util.security.SessionUtil;
import com.qiwenshare.file.api.*;
import com.qiwenshare.file.constant.ApproveStatusEnum;
import com.qiwenshare.file.constant.ApproveTargetTypeEnum;
import com.qiwenshare.file.domain.*;
import com.qiwenshare.file.domain.user.UserBean;
import com.qiwenshare.file.dto.archive.AddArchiveDTO;
import com.qiwenshare.file.dto.archive.ArchiveCodeDTO;
import com.qiwenshare.file.dto.archive.DeleteArchiveDTO;
import com.qiwenshare.file.dto.archive.ModifyArchiveDTO;
import com.qiwenshare.file.mapper.*;
import com.qiwenshare.file.util.SpringBeanUtil;
import com.qiwenshare.file.vo.archive.ArchiveFlowVo;
import com.qiwenshare.file.vo.archive.ArchiveTypeVo;
import com.qiwenshare.file.vo.archive.ArchiveVo;
import com.qiwenshare.file.vo.user.UserLoginVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 档案信息表(Archive)表服务实现类
 *
 * @author makejava
 * @since 2023-10-08 21:09:14
 */
@Service("archiveService")
public class ArchiveServiceImpl extends ServiceImpl<ArchiveMapper, Archive> implements ArchiveService {

    @Autowired
    ArchiveFileService archiveFileService;

    @Autowired
    ArchiveMapper archiveMapper;

    @Autowired
    ArchiveApproveFlowMapper archiveApproveFlowMapper;

    @Autowired
    ArchiveApproveMapper archiveApproveMapper;

    @Autowired
    ArchiveApproveStepService archiveApproveStepService;

    @Autowired
    IUserService userService;

    @Transactional(rollbackOn = Exception.class)
    @Override
    public String add(AddArchiveDTO addArchiveDTO) {
        Archive addArchive = SpringBeanUtil.copyProperties(addArchiveDTO, Archive.class);
        String archiveId = IdUtil.getSnowflakeNextIdStr();
        addArchive.setCreateTime(DateUtil.getCurrentTime());
        addArchive.setCreateUserId(SessionUtil.getSession().getUserId());
        addArchive.setArchiveId(archiveId);
        addArchive.setArchiveCode(generateArchiveCode(addArchiveDTO));
        this.save(addArchive);
        List<ArchiveFile> archiveFileList = addArchiveDTO.getFileList().stream().peek(a -> {
            a.setArchiveId(archiveId);
            a.setArchiveFileId(IdUtil.getSnowflakeNextIdStr());
        }).collect(Collectors.toList());
        archiveFileService.saveBatch(archiveFileList);
        return archiveId;
    }

    @Transactional(rollbackOn = Exception.class)
    @Override
    public String modify(ModifyArchiveDTO modifyArchiveDTO) {
        Archive modifyArchive = SpringBeanUtil.copyProperties(modifyArchiveDTO, Archive.class);
        modifyArchive.setModifyTime(DateUtil.getCurrentTime());
        modifyArchive.setModifyUserId(SessionUtil.getSession().getUserId());
        this.update(modifyArchive, new QueryWrapper<>(Archive.builder()
                .archiveId(modifyArchiveDTO.getArchiveId())
                .build()));

        archiveFileService.remove(new QueryWrapper<>(ArchiveFile.builder()
                .archiveId(modifyArchiveDTO.getArchiveId())
                .build()));

        List<ArchiveFile> archiveFileList = modifyArchiveDTO.getFileList().stream().peek(a -> {
            a.setArchiveId(modifyArchiveDTO.getArchiveId());
            a.setArchiveFileId(IdUtil.getSnowflakeNextIdStr());
        }).collect(Collectors.toList());
        archiveFileService.saveBatch(archiveFileList);
        return modifyArchiveDTO.getArchiveId();
    }

    @Transactional(rollbackOn = Exception.class)
    @Override
    public String delete(DeleteArchiveDTO deleteArchiveDTO) {
        archiveFileService.remove(new QueryWrapper<>(ArchiveFile.builder()
                .archiveId(deleteArchiveDTO.getArchiveId())
                .build()));
        this.remove(new QueryWrapper<>(Archive.builder()
                .archiveId(deleteArchiveDTO.getArchiveId())
                .build()));
        return deleteArchiveDTO.getArchiveId();
    }

    @Override
    public IPage<ArchiveVo> getList(String archiveName, Integer fileType,String archiveTypeId, String archiveCode, String departmentId, String startDate, String endDate, Long currentPage, Long pageCount) {
        Page<ArchiveVo> page = new Page<>(currentPage, pageCount);

        return archiveMapper.selectPageVo(page, archiveName, fileType, archiveTypeId, archiveCode,  departmentId, startDate, endDate);
    }

    @Override
    public IPage<ArchiveVo> getListWithApprove(String archiveName, Integer fileType, String archiveTypeId, String archiveCode, String departmentId, String startDate, String endDate, Long currentPage, Long pageCount) {
        Page<ArchiveVo> page = new Page<>(currentPage, pageCount);

        return archiveMapper.selectPageVoWithApprove(page, archiveName, fileType, SessionUtil.getUserId(), archiveTypeId, archiveCode,  departmentId, startDate, endDate);
    }

    @Transactional(rollbackOn = Exception.class)
    @Override
    public Boolean approve(String archiveId, String userId) {
        ArchiveFlowVo archiveFlowVo = archiveApproveFlowMapper.selectByArchiveId(archiveId);
        String approveId = IdUtil.getSnowflakeNextIdStr();
        List<ArchiveApproveStep> archiveApproveSteps = new ArrayList<>();
        String lastStepId = "";
        String currentStepId = "";
        ArchiveApproveFlowItem currentFlowItem = new ArchiveApproveFlowItem();
        for (int i = 0; i < archiveFlowVo.getItemList().size(); i++) {
            String stepId = IdUtil.getSnowflakeNextIdStr();
            archiveApproveSteps.add(ArchiveApproveStep.builder()
                    .stepId(stepId)
                    .approveId(approveId)
                    .approveResult(archiveFlowVo.getItemList().get(i).getApproveTargetType() == null ? 1 : null)
                    .itemId(archiveFlowVo.getItemList().get(i).getItemId())
                    .build());
            if (i == 0) {
                lastStepId = stepId;
            }
            if (i == 1) {
                currentStepId = stepId;
                currentFlowItem = archiveFlowVo.getItemList().get(i);
            }
        }

        archiveApproveMapper.insert(ArchiveApprove.builder()
                .approveId(approveId)
                .archiveId(archiveId)
                .userId(userId)
                .flowId(archiveFlowVo.getFlowId())
                .lastStepId(lastStepId)
                .currentStepId(currentStepId)
                .currentApproveByIds(getCurrentApproveByIds(userId, archiveId, currentFlowItem))
                .approveStatus(ApproveStatusEnum.PROCESSING.getStatus())
                .createTime(DateUtil.getCurrentTime())
                .build());
        //TODO
        pushApproveNotice();
        return archiveApproveStepService.saveBatch(archiveApproveSteps);
    }

    private void pushApproveNotice() {

    }

    public String getCurrentApproveByIds(String applyBy, String archiveId, ArchiveApproveFlowItem currentFlowItem) {
        List<UserBean> managers = new ArrayList<>();
        switch (Objects.requireNonNull(ApproveTargetTypeEnum.getEnum(currentFlowItem.getApproveTargetType()))) {
            case ARCHIVE_DEPARTMENT_MANAGER:
                managers = userService.getArchiveDepartmentManager(archiveId);
                break;
            case USER_DEPARTMENT_MANAGER:
                managers = userService.getEmployeeDepartmentManager(applyBy);
                break;
            case COMPANY_MANAGER:
                managers = userService.getCeoList();
                break;
        }
        List<String> ids = new ArrayList<>();
        managers.forEach(m -> {
            ids.add(m.getUserId());
        });
        return StringUtils.join(ids.toArray(), ",");
    }

    @Override
    public List<ArchiveTypeVo> getArchiveTypeList() {
        return archiveMapper.getArchiveTypeList();
    }

    private String generateArchiveCode(AddArchiveDTO addArchiveDTO) {
        ArchiveCodeDTO archiveCodeDTO = archiveMapper.getArchiveCode(addArchiveDTO.getDepartmentId());
        archiveCodeDTO.setArchiveLevel(addArchiveDTO.getArchiveLevel().toString());
        archiveCodeDTO.setArchiveType(addArchiveDTO.getArchiveTypeId());
        archiveCodeDTO.setYear(cn.hutool.core.date.DateUtil.format(new Date(), "yyyy"));
        return archiveCodeDTO.getCode();
    }
}

